package com.dingreading.cloud.web.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.DoubleUtil;
import com.dingreading.cloud.common.util.JsonUtil;
import com.dingreading.cloud.common.util.MemberUtil;
import com.dingreading.cloud.web.dto.ReadInterestChoiceDto;
import com.dingreading.cloud.web.dto.ReadInterestChoiceResultDto;
import com.dingreading.cloud.web.dto.ReadInterestQuestionDto;
import com.dingreading.cloud.web.entity.Members;
import com.dingreading.cloud.web.entity.ReadInterestMember;
import com.dingreading.cloud.web.entity.Stores;
import com.dingreading.cloud.web.service.*;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/front/readInterest")
@Api(tags = "前端-阅读兴趣测评")
public class FrontReadInterestController {

    @Resource
    protected ReadInterestQuestionService readInterestQuestionService;
    @Resource
    protected ReadInterestChoiceService readInterestChoiceService;
    @Resource
    protected ReadInterestBookService readInterestBookService;
    @Resource
    protected ReadInterestMemberService readInterestMemberService;
    @Resource
    protected MembersService membersService;
    @Resource
    protected StoresService storeService;

    public static final List<String> typeNames = Lists.newArrayList("科普", "历史", "童话", "冒险", "推理", "成长");

    @ApiOperation(value = "获取会员详情")
    @PostMapping(value = "/getMemberInfo", produces = "application/json; charset=UTF-8")
    public R<Object> getMemberInfo(
            @ApiParam(value = "会员uid") @RequestParam(value = "uid") String uid
    ) {
        Members member = membersService.getByUid(uid);
        if (member == null)
            return R.fail("未查询到会员信息");

        Stores store = storeService.getByUid(member.getStoreUid());
        if (store == null)
            return R.fail("未查询到门店信息");
        if (!store.getEnabled().equals(1))
            return R.fail("门店已被禁用");

        JSONObject jsonObject = new JSONObject();

        JSONObject memberObj = new JSONObject();
        memberObj.put("storeUid", member.getStoreUid());
        memberObj.put("storeName", store.getStoreName());
        memberObj.put("memberUid", member.getUid());
        memberObj.put("memberName", member.getFullName());
        memberObj.put("grade", MemberUtil.getGrade(member.getGrade()));
        jsonObject.put("member", memberObj);

        // 获取会员最新一次的做题结果
        ReadInterestMember data = readInterestMemberService.getLastData(uid);
        if (data != null) {
            JSONObject answerObj = new JSONObject();
            // 基础题目评语
            String suggests = data.getSuggests();
            JSONArray suggestList = null;
            if (StringUtils.isNotBlank(suggests)) {
                suggestList = JSONArray.parseArray(suggests);
            }
            answerObj.put("suggestList", suggestList);

            // 阅读兴趣书单
            String bookNames = data.getBookNames();
            List<String> bookList = null;
            if (StringUtils.isNotBlank(bookNames)) {
                bookList = JSONArray.parseArray(bookNames, String.class);
            }
            answerObj.put("bookList", bookList);

            // 阅读兴趣类型比例
            String interestRadios = data.getInterestRadios();
            JSONArray interestNumList = null;
            if (StringUtils.isNotBlank(interestRadios)) {
                interestNumList = JSONArray.parseArray(interestRadios);
            }
            answerObj.put("interestNumList", interestNumList);
            jsonObject.put("record", answerObj);
        } else {
            jsonObject.put("record", null);
        }
        return R.ok(jsonObject);
    }

    @ApiOperation(value = "基础/兴趣题目列表")
    @PostMapping(value = "/getQuestionList", produces = "application/json; charset=UTF-8")
    public R<Object> getQuestionList(
            @ApiParam(value = "会员uid") @RequestParam(value = "memberUid") String memberUid,
            @ApiParam(value = "阶段 1.初阶 2.中阶 3.高阶") @RequestParam(value = "stage") Integer stage,
            @ApiParam(value = "题目类型 1.基础题目 2.兴趣题目 3.基础+兴趣") @RequestParam(value = "type") Integer type
    ) {
        Members member = membersService.getByUid(memberUid);
        if (member == null)
            return R.fail("未查询到会员信息");
        Stores store = storeService.getByUid(member.getStoreUid());
        if (store == null)
            return R.fail("未查询到门店信息");
        if (!store.getEnabled().equals(1))
            return R.fail("门店已被禁用");

        List<ReadInterestQuestionDto> questionList = new ArrayList<>();

        List<Long> allQuestionIds = new ArrayList<>();
        List<ReadInterestQuestionDto> baseList = new ArrayList<>();
        List<ReadInterestQuestionDto> interestList = new ArrayList<>();
        if (type == null || (!type.equals(1) && !type.equals(2) && !type.equals(3)))
            return R.fail("请选择题目类型");
        if (type.equals(1) || type.equals(3)) {
            // 获取随机基础题目
            List<Long> randomQuestionIds = getRandomQuestionIds(stage);
            if (CollectionUtils.isEmpty(randomQuestionIds))
                return R.fail("随机基础题目获取失败");
            baseList = readInterestQuestionService.dtoListByIds(randomQuestionIds);
            if (CollectionUtils.isEmpty(baseList))
                return R.fail("基础题目获取失败");
            allQuestionIds.addAll(randomQuestionIds);
        }
        if (type.equals(2) || type.equals(3)) {
            // 获取兴趣题目
            interestList = readInterestQuestionService.getInterestQuestionList();
            if (CollectionUtils.isEmpty(interestList))
                return R.fail("兴趣题目获取失败");
            List<Long> questionIds = interestList.stream().map(ReadInterestQuestionDto::getId).collect(Collectors.toList());
            allQuestionIds.addAll(questionIds);
        }

        // 获取题目的选择项
        Map<Long, List<ReadInterestChoiceDto>> choiceMap = new HashMap<>();
        List<ReadInterestChoiceDto> choiceList = readInterestChoiceService.dtoListByQuestionIds(allQuestionIds);
        if (CollectionUtils.isNotEmpty(choiceList))
            choiceMap = choiceList.stream().collect(Collectors.groupingBy(ReadInterestChoiceDto::getQuestionId));

        if (type.equals(1) || type.equals(3)) {
            // 基础题目添加选择项
            questionList.addAll(getBaseQuestion(baseList, choiceMap));
        }
        if (type.equals(2) || type.equals(3)) {
            // 兴趣题目添加选择项
            getInterestQuestion(interestList, choiceMap);
            questionList.addAll(interestList);
        }

        // 按侧重点分组
        Map<List<Object>, List<ReadInterestQuestionDto>> questionMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(questionList)) {
            // 侧重点分组
            Function<ReadInterestQuestionDto, List<Object>> compositeKey =
                    question -> Arrays.asList(question.getEmphasisType(), question.getEmphasisName());
            questionMap = questionList.stream()
                    .filter(question -> question.getParentId().equals(0L))
                    .collect(Collectors.groupingBy(compositeKey, LinkedHashMap::new, Collectors.toList()));
        }

        return R.ok(questionMap);
    }

    @ApiOperation(value = "提交答案")
    @PostMapping(value = "/submitAnswer", produces = "application/json; charset=UTF-8")
    public R<Object> submitAnswer(
            @ApiParam(value = "会员uid") @RequestParam(value = "memberUid") String memberUid,
            @ApiParam(value = "题目选择项id集合") @RequestParam(value = "choiceIds") List<Long> choiceIds,
            @ApiParam(value = "阶段 1.初阶 2.中阶 3.高阶") @RequestParam(value = "stage") Integer stage,
            @ApiParam(value = "题目类型 1.基础题目 2.兴趣题目 3.基础+兴趣") @RequestParam(value = "type") Integer type
    ) {
        Members member = membersService.getByUid(memberUid);
        if (member == null)
            return R.fail("未查询到会员信息");
        Stores store = storeService.getByUid(member.getStoreUid());
        if (store == null)
            return R.fail("未查询到门店信息");
        if (!store.getEnabled().equals(1))
            return R.fail("门店已被禁用");

        List<ReadInterestChoiceResultDto> choiceList = readInterestChoiceService.listByQuestionInfo(choiceIds);
        if (CollectionUtils.isEmpty(choiceList))
            return R.fail("获取答题选择项失败");

        JSONObject jsonObject = new JSONObject();

        JSONObject memberObj = new JSONObject();
        memberObj.put("storeUid", member.getStoreUid());
        memberObj.put("storeName", store.getStoreName());
        memberObj.put("memberUid", member.getUid());
        memberObj.put("memberName", member.getFullName());
        memberObj.put("grade", MemberUtil.getGrade(member.getGrade()));
        jsonObject.put("member", memberObj);

        List<ReadInterestChoiceResultDto> baseList = new ArrayList<>();
        List<ReadInterestChoiceResultDto> interestList = new ArrayList<>();
        for (ReadInterestChoiceResultDto choice : choiceList) {
            if (choice.getEmphasisType().equals(4)) {
                // 兴趣题目选择项
                interestList.add(choice);
            } else {
                // 基础题目选择项
                baseList.add(choice);
            }
        }

        JSONObject answerObj = new JSONObject();
        // 基础题目
        JSONArray suggestList = null;
        if (CollectionUtils.isNotEmpty(baseList)) {
            suggestList = getSuggestList(baseList);
        }
        answerObj.put("suggestList", suggestList);

        // 兴趣题目
        List<String> bookList = null;
        JSONArray interestNumList = null;
        if (CollectionUtils.isNotEmpty(interestList)) {
            Function<ReadInterestChoiceResultDto, List<Object>> interestKeys = choice ->
                    Arrays.asList(choice.getInterestType(), choice.getInterestTypeName());
            Map<List<Object>, List<ReadInterestChoiceResultDto>> integerMap = interestList.stream()
                    .collect(Collectors.groupingBy(interestKeys, LinkedHashMap::new, Collectors.toList()));

            int total = interestList.size();
            interestNumList = new JSONArray();
            List<Integer> interestTypes = new ArrayList<>();
            List<Integer> interestTypeNums = new ArrayList<>();
            for (Map.Entry<List<Object>, List<ReadInterestChoiceResultDto>> entry : integerMap.entrySet()) {
                List<Object> keys = entry.getKey();
                Integer interestType = (Integer) keys.get(0);
                String interestTypeName = (String) keys.get(1);
                List<ReadInterestChoiceResultDto> value = entry.getValue();

                // 兴趣类型的次数
                int num = value.size();
                // 兴趣类型选择比例
                double radio = DoubleUtil.divFloor(num, total, 2) * 100;
                // 选择类型的比例集合
                interestNumList.add(getJSONObject(interestTypeName, num, radio + "%"));

                // 按比例获取选书数量
                double bookNum = DoubleUtil.divFloor(num, total, 1) * 10;
                if (bookNum > 0) {
                    // 兴趣类型集合
                    interestTypes.add(interestType);
                    // 兴趣次数集合
                    interestTypeNums.add((int) bookNum);
                }

                // 删除已有的兴趣类型
                typeNames.remove(interestTypeName);
            }

            // 根据选择项，分组后随机获取书籍
            bookList = readInterestBookService.getBookList(stage, interestTypes, interestTypeNums);

            // 补充未选的兴趣类型
            if (CollectionUtils.isNotEmpty(typeNames)) {
                for (String typeName : typeNames) {
                    interestNumList.add(getJSONObject(typeName, 0, null));
                }
            }
        }
        // 推荐书单
        answerObj.put("bookList", bookList);
        // 兴趣比例
        answerObj.put("interestNumList", interestNumList);

        jsonObject.put("record", answerObj);

        // 保存会员答题结果
        saveMemberRecord(member, store, stage, type, choiceIds, suggestList, bookList, interestNumList);

        return R.ok(jsonObject);
    }

    /**
     * 保存会员答题结果
     */
    private void saveMemberRecord(
            Members member, Stores store, Integer stage, Integer questionType, List<Long> choiceIds,
            JSONArray suggestList, List<String> bookList, JSONArray interestNumList
    ) {
        ReadInterestMember data = new ReadInterestMember();
        data.setCorpUid(store.getCorpUid());
        data.setStoreUid(store.getUid());
        data.setStoreName(store.getStoreName());
        data.setMemberUid(member.getUid());
        data.setFullName(member.getFullName());
        data.setMemberName(member.getMemberName());
        data.setStage(stage);
        data.setQuestionType(questionType);
        data.setChoiceIds(choiceIds.toString());
        if (CollectionUtils.isNotEmpty(bookList))
            data.setBookNames(JsonUtil.toJsonString(bookList));
        if (interestNumList != null)
            data.setInterestRadios(interestNumList.toJSONString());
        if (suggestList != null)
            data.setSuggests(suggestList.toJSONString());
        readInterestMemberService.save(data);
    }

    /**
     * 处理基础题目的结果
     */
    private JSONArray getSuggestList(List<ReadInterestChoiceResultDto> baseList) {
        LinkedHashMap<String, List<ReadInterestChoiceResultDto>> map = baseList.stream()
                .collect(Collectors.groupingBy(ReadInterestChoiceResultDto::getEmphasisName, LinkedHashMap::new, Collectors.toList()));

        JSONArray contentList = new JSONArray();
        for (Map.Entry<String, List<ReadInterestChoiceResultDto>> entry : map.entrySet()) {
            String key = entry.getKey();
            List<ReadInterestChoiceResultDto> value = entry.getValue();

            List<String> rightList = new ArrayList<>();
            List<String> suggestList = new ArrayList<>();
            for (ReadInterestChoiceResultDto dto : value) {
                if (dto.getRightStatus().equals(1)) {
                    // 回答正确
                    rightList.add(dto.getEmphasisChildName());
                } else {
                    // 回答错误，返回评语
                    suggestList.add(dto.getContent());
                }
            }

            JSONObject typeObj = new JSONObject();
            typeObj.put("emphasisType", key);

            JSONObject contentObj = new JSONObject();
            contentObj.put("rightList", rightList);
            contentObj.put("suggestList", suggestList);
            typeObj.put("content", contentObj);

            contentList.add(typeObj);
        }
        return contentList;
    }

    /**
     * 获取随机基础题目的id
     */
    private List<Long> getRandomQuestionIds(int stage) {
        // 获取随机数和id，拼接格式：随机数.id
        List<String> randomNumberAndIds = readInterestQuestionService.randomNumberAndIds(stage);

        List<Long> randomQuestionIds = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(randomNumberAndIds)) {
            for (String randomNumberAndId : randomNumberAndIds) {
                String[] split = randomNumberAndId.split("\\.");
                String id = split[1];
                if (StringUtils.isBlank(id))
                    break;
                randomQuestionIds.add(Long.valueOf(id));
            }
        }
        return randomQuestionIds;
    }

    /**
     * 基础题目添加选择项
     */
    private List<ReadInterestQuestionDto> getBaseQuestion(List<ReadInterestQuestionDto> list, Map<Long, List<ReadInterestChoiceDto>> choiceMap) {
        // 将基础题目分为组合题目和普通题目
        List<ReadInterestQuestionDto> questionResultList = new ArrayList<>();
        Map<Long, List<ReadInterestQuestionDto>> parentQuestionMap = new HashMap<>();

        for (ReadInterestQuestionDto question : list) {
            Long parentId = question.getParentId();
            if (!parentId.equals(0L)) {
                List<ReadInterestQuestionDto> parentQuestionList = parentQuestionMap.get(parentId);
                if (CollectionUtils.isEmpty(parentQuestionList)) {
                    parentQuestionMap.put(parentId, Lists.newArrayList(question));
                } else {
                    parentQuestionList.add(question);
                    parentQuestionMap.put(parentId, parentQuestionList);
                }
            } else {
                questionResultList.add(question);
            }
        }

        // 获取组合题目的父题目
        Map<Long, ReadInterestQuestionDto> parentQuestionResultMap = new HashMap<>();
        if (parentQuestionMap.size() > 0) {
            Set<Long> parentQuestionIds = parentQuestionMap.keySet();
            List<ReadInterestQuestionDto> parentQuestions = readInterestQuestionService.dtoListByIds(new ArrayList<>(parentQuestionIds));
            parentQuestionResultMap = parentQuestions.stream().collect(Collectors.toMap(ReadInterestQuestionDto::getId, Function.identity()));
        }

        List<ReadInterestQuestionDto> questionList = new ArrayList<>();

        // 普通题目添加选择项
        for (ReadInterestQuestionDto question : questionResultList) {
            question.setChoiceList(choiceMap.get(question.getId()));
            questionList.add(question);
        }
        // 组合题目添加选择项
        if (parentQuestionResultMap.size() > 0) {
            for (Map.Entry<Long, ReadInterestQuestionDto> entry : parentQuestionResultMap.entrySet()) {
                Long key = entry.getKey();
                ReadInterestQuestionDto value = entry.getValue();

                List<ReadInterestQuestionDto> questionDtoList = parentQuestionMap.get(key);
                for (ReadInterestQuestionDto question : questionDtoList) {
                    question.setChoiceList(choiceMap.get(question.getId()));
                }
                value.setQuestionList(questionDtoList);

                questionList.add(value);
            }
        }

        return questionList;
    }

    /**
     * 兴趣题目添加选择项
     */
    private void getInterestQuestion(List<ReadInterestQuestionDto> list, Map<Long, List<ReadInterestChoiceDto>> choiceMap) {
        for (ReadInterestQuestionDto question : list) {
            question.setChoiceList(choiceMap.get(question.getId()));
        }
    }

    /**
     * 兴趣选择比例实体
     */
    private JSONObject getJSONObject(String name, int num, String radio) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name", name);
        jsonObject.put("num", num);
        jsonObject.put("radio", radio);
        return jsonObject;
    }
}